package net.lucode.hackware.magicindicator.buildins.commonnavigator.indicators;

import net.lucode.hackware.magicindicator.FragmentContainerHelper;
import net.lucode.hackware.magicindicator.buildins.ArgbEvaluatorHolder;
import net.lucode.hackware.magicindicator.buildins.UIUtil;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IPagerIndicator;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.model.PositionData;
import ohos.agp.animation.Animator;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.Path;
import ohos.agp.utils.Color;
import ohos.app.Context;

import java.util.Arrays;
import java.util.List;

/**
 * 贝塞尔曲线ViewPager指示器，带颜色渐变
 *
 * @since 2020-09-29
 */
public class BezierPagerIndicator extends Component implements IPagerIndicator, Component.DrawTask {
    private List<PositionData> mPositionDataList;

    private float mLeftCircleRadius;
    private float mLeftCircleX;
    private float mRightCircleRadius;
    private float mRightCircleX;

    private float mYOffset;
    private float mMaxCircleRadius;
    private float mMinCircleRadius;

    private Paint mPaint;
    private Path mPath = new Path();

    private List<Integer> mColors;
    private int mStartInterpolator = Animator.CurveType.ACCELERATE;
    private int mEndInterpolator = Animator.CurveType.DECELERATE;

    /**
     * BezierPagerIndicator
     *
     * @param context context
     */
    public BezierPagerIndicator(Context context) {
        super(context);
        init(context);
    }

    private void init(Context context) {
        mPaint = new Paint();
        mPaint.setSubpixelAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILL_STYLE);
        mMaxCircleRadius = UIUtil.vp2px(context, 3.5f);
        mMinCircleRadius = UIUtil.vp2px(context, 2);
        mYOffset = UIUtil.vp2px(context, 1.5f);
        addDrawTask(this);
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        canvas.drawCircle(mLeftCircleX, getHeight() - mYOffset - mMaxCircleRadius, mLeftCircleRadius, mPaint);
        canvas.drawCircle(mRightCircleX, getHeight() - mYOffset - mMaxCircleRadius, mRightCircleRadius, mPaint);
        drawBezierCurve(canvas);
    }

    /**
     * 绘制贝塞尔曲线
     *
     * @param canvas
     */
    private void drawBezierCurve(Canvas canvas) {
        mPath.reset();
        float height = getHeight() - mYOffset - mMaxCircleRadius;
        mPath.moveTo(mRightCircleX, height);
        mPath.lineTo(mRightCircleX, height - mRightCircleRadius);
        mPath.quadTo(mRightCircleX + (mLeftCircleX - mRightCircleX) / 2.0f,
                height, mLeftCircleX, height - mLeftCircleRadius);
        mPath.lineTo(mLeftCircleX, height + mLeftCircleRadius);
        mPath.quadTo(mRightCircleX + (mLeftCircleX - mRightCircleX) / 2.0f,
                height, mRightCircleX, height + mRightCircleRadius);
        mPath.close(); // 闭合
        canvas.drawPath(mPath, mPaint);
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        if (mPositionDataList == null || mPositionDataList.isEmpty()) {
            return;
        }
        int nextPosition = position + 1;
        if (positionOffsetPixels < 0) {
            nextPosition = position - 1;
        }

        // 计算颜色
        if (mColors != null && mColors.size() > 0) {
            int currentColor = mColors.get(Math.abs(position) % mColors.size());
            int nextColor = mColors.get(Math.abs(nextPosition) % mColors.size());
            int color = ArgbEvaluatorHolder.eval(positionOffset, currentColor, nextColor);
            mPaint.setColor(new Color(color));
        }

        // 计算锚点位置
        PositionData current = FragmentContainerHelper.getImitativePositionData(mPositionDataList, position);
        PositionData next = FragmentContainerHelper.getImitativePositionData(mPositionDataList, nextPosition);

        float leftX = current.mLeft + (current.mRight - current.mLeft) / 2;
        float rightX = next.mLeft + (next.mRight - next.mLeft) / 2;

        mLeftCircleX = leftX + (rightX - leftX) * UIUtil.getInterpolation(mStartInterpolator, positionOffset);
        mRightCircleX = leftX + (rightX - leftX) * UIUtil.getInterpolation(mEndInterpolator, positionOffset);
        mLeftCircleRadius = mMaxCircleRadius
                + (mMinCircleRadius - mMaxCircleRadius) * UIUtil.getInterpolation(mEndInterpolator, positionOffset);
        mRightCircleRadius = mMinCircleRadius
                + (mMaxCircleRadius - mMinCircleRadius) * UIUtil.getInterpolation(mStartInterpolator, positionOffset);

        addDrawTask(this);
    }

    @Override
    public void onPageSelected(int position) {
    }

    @Override
    public void onPageScrollStateChanged(int state) {
    }

    @Override
    public void onPositionDataProvide(List<PositionData> dataList) {
        mPositionDataList = dataList;
    }

    /**
     * getMaxCircleRadius
     *
     * @return mMaxCircleRadius
     */
    public float getMaxCircleRadius() {
        return mMaxCircleRadius;
    }

    /**
     * setMaxCircleRadius
     *
     * @param maxCircleRadius maxCircleRadius
     */
    public void setMaxCircleRadius(float maxCircleRadius) {
        mMaxCircleRadius = maxCircleRadius;
    }

    /**
     * getMinCircleRadius
     *
     * @return mMinCircleRadius
     */
    public float getMinCircleRadius() {
        return mMinCircleRadius;
    }

    /**
     * setMinCircleRadius
     *
     * @param minCircleRadius minCircleRadius
     */
    public void setMinCircleRadius(float minCircleRadius) {
        mMinCircleRadius = minCircleRadius;
    }

    /**
     * getYOffset
     *
     * @return mYOffset
     */
    public float getYOffset() {
        return mYOffset;
    }

    /**
     * setYOffset
     *
     * @param yOffset yOffset
     */
    public void setYOffset(float yOffset) {
        mYOffset = yOffset;
    }

    /**
     * setColors
     *
     * @param colors colors
     */
    public void setColors(Integer... colors) {
        mColors = Arrays.asList(colors);
    }

    /**
     * setStartInterpolator
     *
     * @param startInterpolator startInterpolator
     */
    public void setStartInterpolator(int startInterpolator) {
        mStartInterpolator = startInterpolator;
    }

    /**
     * setEndInterpolator
     *
     * @param endInterpolator endInterpolator
     */
    public void setEndInterpolator(int endInterpolator) {
        mEndInterpolator = endInterpolator;
    }
}
